package cn.myjerry.collection;

/**
 * 自定义LinkedList容器
 * @author Jerry
 */

public class SxtLinkedList {
	
	private Node first;
	private Node last;
	private int size;
	
	public SxtLinkedList() {}

	public int size() {
		return size;
	}
	
	public void add(Object obj) {
		Node n = new Node();
		if(first == null) {
			n.setPrev(null);
			n.setObj(obj);
			n.setNext(null);
			
			first = n;
			last = n;
			
		} else {
			n.setPrev(last);
			n.setObj(obj);
			n.setNext(null);
			
			last.setNext(n);
			
			last = n;
		}
		size++;
	}
	
	public Object get(int index) {
		rangeCheck(index);
		return node(index).obj;
	}

	public Node node (int index) {
		Node n = null;
		if(first != null) {
			if(index < ( size >> 1 )) {
				n = first;
				for(int i=0;i<index;i++) {
					n = n.next;
				}
			} else {
				n = last;
				for(int i=size-1;i>index;i--) {
					n = n.prev;
				}
			}
		}
		return n;
	}
	
	public void add(int index, Object obj) {
		rangeCheck(index);
		Node n = node(index);
		Node newNode = new Node();
		newNode.obj = obj;
		if(n != null ) {
			Node up = n.prev;
			newNode.prev = up;
			up.next = newNode;
			
			newNode.next = n;
			n.prev = newNode;
			
			size++;
		}
	}
	
	public void remove(int index) {
		rangeCheck(index);
		Node n = node(index);
		if(n != null) {
			Node up = n.prev;
			Node down = n.next;
			
			up.next = down;
			down.prev = up;
			size--;
		}
	}
	
	public void set(int index, Object obj) {
		rangeCheck(index);
		Node n = node(index);
		if(n != null) {
			n.obj = obj;
		}
	}
	
	public void rangeCheck(int index) {
		if(index<0 || index >= size) {
			try {
				throw new Exception();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	public static void main(String[] args) {
		SxtLinkedList list = new SxtLinkedList();

		list.add("Jerry");
		list.add(317);
		list.add("Tom");
		list.add("Kim");
		list.add("Davy");

		System.out.println(list.get(3));
		System.out.println(list.get(4));
		list.add(3, "Bobi");
		System.out.println(list.get(3));
		System.out.println(list.get(4));
		
	}
}

class Node {
	Object obj;
	Node prev;
	Node next;
	
	public Node () {}
	
	public Node(Object obj, Node prev, Node next) {
		super();
		this.obj = obj;
		this.prev = prev;
		this.next = next;
	}

	/**
	 * @return the obj
	 */
	public Object getObj() {
		return obj;
	}

	/**
	 * @param obj the obj to set
	 */
	public void setObj(Object obj) {
		this.obj = obj;
	}

	/**
	 * @return the prev
	 */
	public Node getPrev() {
		return prev;
	}

	/**
	 * @param prev the prev to set
	 */
	public void setPrev(Node prev) {
		this.prev = prev;
	}

	/**
	 * @return the next
	 */
	public Node getNext() {
		return next;
	}

	/**
	 * @param next the next to set
	 */
	public void setNext(Node next) {
		this.next = next;
	}
	
}